using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using Unity.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

namespace Framework
{
    public static partial class Utils
    {
        public static class File
        {
            public static string GetMD5(string data)
            {
                return GetMD5(Encoding.GetEncoding("utf-8").GetBytes(data));
            }

            /// <summary>
            /// 获取二进制数组的md5
            /// </summary>
            /// <param name="data">二进制数据</param>
            /// <returns>md5</returns>
            public static string GetMD5(byte[] data)
            {
                string md5Str = "";
                MD5 md5 = new MD5CryptoServiceProvider();
                byte[] bytes = md5.ComputeHash(data);
                for (int i = 0; i < bytes.Length; i++)
                {
                    md5Str += bytes[i].ToString("x2");
                }
                return md5Str;
            }
            public static string GetRegularPath(string path)
            {
                if (path == null)
                {
                    return null;
                }
                return path.Replace('\\', '/');
            }
            public static string GetFileNameWithoutExtension(string fileName)
            {
                int startIndex = fileName.LastIndexOf('/');
                if (startIndex <= 0)
                {
                    startIndex = 0;
                }
                else
                {
                    startIndex += 1;
                }
                int endIndex = fileName.LastIndexOf('.');
                if (startIndex <= 0 && endIndex <= 0)
                {
                    return fileName;
                }
                if (endIndex <= 0)
                {
                    endIndex = fileName.Length;
                }
                return fileName.Substring(startIndex, endIndex - startIndex);
            }

            public static string GetFilePathWithoutExtension(string fileName)
            {
                int startIndex = 0;
                int endIndex = fileName.LastIndexOf('.');
                if (startIndex <= 0 && endIndex <= 0)
                {
                    return fileName;
                }
                if (endIndex <= 0)
                {
                    endIndex = fileName.Length;
                }
                return fileName.Substring(startIndex, endIndex - startIndex);
            }
            public static int CopyFolder(string sourceFolder, string destFolder, bool overwrite = true)
            {
                try
                {
                    //如果目标路径不存在,则创建目标路径
                    if (!System.IO.Directory.Exists(destFolder))
                    {
                        System.IO.Directory.CreateDirectory(destFolder);
                    }
                    //得到原文件根目录下的所有文件
                    string[] files = System.IO.Directory.GetFiles(sourceFolder);
                    foreach (string file in files)
                    {
                        string name = System.IO.Path.GetFileName(file);
                        string dest = System.IO.Path.Combine(destFolder, name);
                        if (!overwrite)
                        {
                            if (System.IO.File.Exists(dest))
                            {
                                continue;
                            }
                        }
                        System.IO.File.Copy(file, dest, true);//复制文件
                    }
                    //得到原文件根目录下的所有文件夹
                    string[] folders = System.IO.Directory.GetDirectories(sourceFolder);
                    foreach (string folder in folders)
                    {
                        string name = System.IO.Path.GetFileName(folder);
                        string dest = System.IO.Path.Combine(destFolder, name);
                        CopyFolder(folder, dest);//构建目标路径,递归复制文件
                    }
                    return 1;
                }
                catch (Exception)
                {
                    throw;
                }
            }

            public static void WriteAllBytes(string filePath, byte[] buffer, int length = 0)
            {
                if (length < 1)
                {
                    length = buffer.Length;
                }
                if (string.IsNullOrEmpty(filePath))
                {
                    return;
                }
                try
                {
                    var fileInfo = new FileInfo(filePath);
                    var dirInfo = fileInfo.Directory;
                    if (dirInfo != null && !dirInfo.Exists)
                    {
                        Directory.CreateDirectory(dirInfo.FullName);
                    }
                    if (System.IO.File.Exists(filePath))
                    {
                        System.IO.File.Delete(filePath);
                    }
                    using var fileStream = new FileStream(filePath, FileMode.Create);
                    fileStream.Write(buffer, 0, length);
                    fileStream.Flush();
                    fileStream.Close();
                }
                catch (System.Exception)
                {

                    throw;
                }

            }
            public static void WriteAllBytes(string filePath, NativeArray<byte>.ReadOnly buffer)
            {
                if (string.IsNullOrEmpty(filePath))
                {
                    return;
                }
                try
                {
                    var fileInfo = new FileInfo(filePath);
                    var dirInfo = fileInfo.Directory;
                    if (dirInfo != null && !dirInfo.Exists)
                    {
                        Directory.CreateDirectory(dirInfo.FullName);
                    }
                    if (System.IO.File.Exists(filePath))
                    {
                        System.IO.File.Delete(filePath);
                    }
                    var length = buffer.Length;
                    using var fileStream = System.IO.File.Create(filePath, length);
                    fileStream.Seek(0, SeekOrigin.Begin);
                    for (int i = 0; i < length; i++)
                    {
                        fileStream.WriteByte(buffer[i]);
                    }
                    fileStream.Flush();
                    fileStream.Close();
                }
                catch (System.Exception)
                {

                    throw;
                }

            }

            private static Dictionary<int, Queue<Byte[]>> _bytebufferPool = new Dictionary<int, Queue<byte[]>>();
            public static byte[] GetByteBuffer(int length)
            {
                var key = Mathf.NextPowerOfTwo(length);
                if (_bytebufferPool.TryGetValue(key, out Queue<Byte[]> list))
                {
                    if (list.Count > 0)
                    {
                        return list.Dequeue();
                    }
                }
                var buffer = new byte[key];
                return buffer;
            }
            public static void ReleaseByteBuffer(byte[] value)
            {
                if (Mathf.IsPowerOfTwo(value.Length))
                {
                    var key = Mathf.NextPowerOfTwo(value.Length);
                    if (!_bytebufferPool.TryGetValue(key, out Queue<Byte[]> list))
                    {
                        list = new Queue<byte[]>();
                        _bytebufferPool.Add(key, list);
                    }
                    list.Enqueue(value);
                }

            }
            public static string GetCurrentScriptFilePath([System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "")
            {
                return sourceFilePath;
            }
            public static string GetAssetsPathByAbsPath(string path)
            {
                var p1 = new Uri(path).AbsolutePath;
                var p2 = new Uri(Application.dataPath).AbsolutePath;
                return "Assets" + p1.Replace(p2, "");
            }

            public static int ReadInt32FromBytes(byte[] bytes, int offset)
            {
                if (bytes == null)
                {
                    throw new ArgumentNullException(nameof(bytes));
                }

                if (offset < 0 || offset + sizeof(int) > bytes.Length)
                {
                    throw new ArgumentOutOfRangeException(nameof(offset), "The offset is out of range.");
                }

                return BitConverter.ToInt32(bytes, offset);
            }
            public static short ReadInt16FromBytes(byte[] bytes, int offset)
            {
                if (bytes == null)
                {
                    throw new ArgumentNullException(nameof(bytes));
                }

                if (offset < 0 || offset + sizeof(short) > bytes.Length)
                {
                    throw new ArgumentOutOfRangeException(nameof(offset), "The offset is out of range.");
                }

                return BitConverter.ToInt16(bytes, offset);
            }
        }
    }
}